package com.code.generator;

import com.google.common.io.Files;
import com.code.generator.AbstractGenerator;
import com.code.generator.model.GeneratorConfiguration;
import com.code.util.JarUtils;
import com.code.util.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

public class ProjectGenerator extends AbstractGenerator {
    public ProjectGenerator() {
    }

    public void generate(GeneratorConfiguration conf) throws Exception {
        this.saveUserCustomConfig(conf);//保存配置
        File projectDir = new File(conf.getRootProjectDirectory());
        if(!projectDir.exists()) {
            FileUtils.forceMkdir(projectDir);
        } else if(projectDir.listFiles().length > 0) {
            throw new Exception("目录【" + projectDir.getAbsolutePath() + "】已存在文件，请选择空的目录来生成项目");
        }

        URL baseProjectURL = Thread.currentThread().getContextClassLoader().getResource("project");
        JarUtils.copyResourcesRecursivelyExcludeTop(baseProjectURL, projectDir);
        if(!conf.isUseRpcModule()) {
            this.deleteRpcModule(projectDir, conf);
        }

        if(!conf.isUseIsRpcModule()) {
            this.deleteIsRpcModule(projectDir, conf);
        }

        if(!conf.isUseWorkModule()) {
            this.deleteWorkModule(projectDir, conf);
        }

        this.removeUnusedDependencies(projectDir, conf);
        if(!conf.isNeedSharding()) {
            this.deleteDbShardingConfig(projectDir, conf);
        }

        if(!conf.isUseRedis()) {
            this.deleteRedisConfig(projectDir, conf);
        }

        if(!conf.isNeedBaseUser()) {
            this.deleteBaseUserConfig(projectDir, conf);
        }

        if(!conf.isUseSafServer()) {
            this.deleteSafServerConf(projectDir, conf);
        }

        if(!conf.isUseSafClient()) {
            this.deleteSafClientConf(projectDir, conf);
        }

        if(!conf.isUseMQ()) {
            this.deleteMQConf(projectDir, conf);
        }

        if(!conf.isUseZookeeper()) {
            this.deleteZookeeperConf(projectDir, conf);
        }

        this.filterFile(projectDir, conf);
        this.generatePackageDirectory(projectDir, conf);
    }

    private void deleteIsRpcModule(File projectDir, GeneratorConfiguration conf) {
        File useIsRpcConfFile = new File(projectDir, "jd-scaffold-isrpc");
        FileUtils.deleteQuietly(useIsRpcConfFile);
        File useIsRpcApiConfFile = new File(projectDir, "jd-scaffold-api");
        FileUtils.deleteQuietly(useIsRpcApiConfFile);
        this.removeModule(projectDir, "<module>jd-scaffold-isrpc</module>", conf);
        this.removeModule(projectDir, "<module>jd-scaffold-saf-api</module>", conf);
        File servicePomFile = new File(projectDir, "jd-scaffold-web/pom.xml");
        FileInputStream fis = null;
        String content = "";

        try {
            fis = new FileInputStream(servicePomFile);
            content = IOUtils.toString(fis, conf.getEncoding());
            content = this.replaceDependencies((String)null, "jd-scaffold-isrpc", content);
        } catch (Exception var21) {
            throw new RuntimeException("remove isrpc module dependency error: " + var21.getMessage());
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(servicePomFile);
            IOUtils.write(content, fos, conf.getEncoding());
        } catch (Exception var19) {
            throw new RuntimeException("remove isrpc module dependency error: " + var19.getMessage());
        } finally {
            IOUtils.closeQuietly(fos);
        }

    }

    private void deleteRpcModule(File projectDir, GeneratorConfiguration conf) {
        File useRpcConfFile = new File(projectDir, "jd-scaffold-rpc");
        FileUtils.deleteQuietly(useRpcConfFile);
        this.removeModule(projectDir, "<module>jd-scaffold-rpc</module>", conf);
        File servicePomFile = new File(projectDir, "jd-scaffold-service/pom.xml");
        FileInputStream fis = null;
        String content = "";

        try {
            fis = new FileInputStream(servicePomFile);
            content = IOUtils.toString(fis, conf.getEncoding());
            content = this.replaceDependencies((String)null, "jd-scaffold-rpc", content);
        } catch (Exception var20) {
            throw new RuntimeException("remove rpc module dependency error: " + var20.getMessage());
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(servicePomFile);
            IOUtils.write(content, fos, conf.getEncoding());
        } catch (Exception var18) {
            throw new RuntimeException("remove rpc module dependency error: " + var18.getMessage());
        } finally {
            IOUtils.closeQuietly(fos);
        }

    }

    private void deleteWorkModule(File projectDir, GeneratorConfiguration conf) {
        File useRpcConfFile = new File(projectDir, "jd-scaffold-work");
        FileUtils.deleteQuietly(useRpcConfFile);
        this.removeModule(projectDir, "<module>jd-scaffold-work</module>", conf);
        File servicePomFile = new File(projectDir, "jd-scaffold-web/pom.xml");
        FileInputStream fis = null;
        String content = "";

        try {
            fis = new FileInputStream(servicePomFile);
            content = IOUtils.toString(fis, conf.getEncoding());
            content = this.replaceDependencies((String)null, "jd-scaffold-work", content);
        } catch (Exception var20) {
            throw new RuntimeException("remove work module dependency error: " + var20.getMessage());
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(servicePomFile);
            IOUtils.write(content, fos, conf.getEncoding());
        } catch (Exception var18) {
            throw new RuntimeException("remove work module dependency error: " + var18.getMessage());
        } finally {
            IOUtils.closeQuietly(fos);
        }

    }

    private void deleteZookeeperConf(File projectDir, GeneratorConfiguration conf) {
        File userSafConfFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-zookeeper.xml");
        FileUtils.deleteQuietly(userSafConfFile);
        this.removeSpringConfig(projectDir, "spring-config-zookeeper.xml", conf);
    }

    private void deleteMQConf(File projectDir, GeneratorConfiguration conf) {
        File userSafConfFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-mq.xml");
        FileUtils.deleteQuietly(userSafConfFile);
        this.removeSpringConfig(projectDir, "spring-config-mq.xml", conf);
    }

    private void deleteSafClientConf(File projectDir, GeneratorConfiguration conf) {
        File userSafConfFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-saf-client.xml");
        FileUtils.deleteQuietly(userSafConfFile);
        this.removeSpringConfig(projectDir, "spring-config-saf-client.xml", conf);
    }

    private void deleteSafServerConf(File projectDir, GeneratorConfiguration conf) {
        File userSafConfFile = new File(projectDir, "jd-scaffold-isrpc/src/main/resources/spring/spring-config-saf-provider.xml");
        FileUtils.deleteQuietly(userSafConfFile);
        this.removeWebSpringConfig(projectDir, "spring-config-saf-provider.xml", conf);
    }

    private void deleteDbShardingConfig(File projectDir, GeneratorConfiguration conf) throws IOException {
        File datasourceConfFile = new File(projectDir, "jd-scaffold-web/src/main/resources/spring/spring-config-datasource.xml");
        FileInputStream is = null;
        String content = null;

        try {
            is = new FileInputStream(datasourceConfFile);
            content = IOUtils.toString(is);
            String e = "[ ]*<ds:sharding-config>([\\s\\S])*?</ds:sharding-config>[ ]*";
            content = content.replaceAll(e, "");
        } catch (Exception var10) {
            throw new RuntimeException("delete db sharding config error.", var10);
        } finally {
            IOUtils.closeQuietly(is);
        }

        Files.write(content.getBytes(Charset.forName(conf.getEncoding())), datasourceConfFile);
    }

    private void deleteBaseUserConfig(File projectDir, GeneratorConfiguration conf) {
        File userSafConfFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-saf-client.xml");
        FileUtils.deleteQuietly(userSafConfFile);
        this.removeCommonProperties(projectDir, "saf.user", conf);
        this.removeSpringConfig(projectDir, "spring-config-saf-client.xml", conf);
    }

    private void deleteRedisConfig(File projectDir, GeneratorConfiguration conf) {
        File redisConfFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-redis.xml");
        FileUtils.deleteQuietly(redisConfFile);
        this.removeCommonProperties(projectDir, "redis.", conf);
        this.removeSpringConfig(projectDir, "spring-config-redis.xml", conf);
    }

    private void removeModule(File projectDir, String s, GeneratorConfiguration conf) {
        File springConfigFile = new File(projectDir, "pom.xml");
        FileInputStream fis = null;
        List lines = null;

        try {
            fis = new FileInputStream(springConfigFile);
            lines = IOUtils.readLines(fis, conf.getEncoding());
            Iterator fos = lines.iterator();

            while(fos.hasNext()) {
                if(((String)fos.next()).contains(s)) {
                    fos.remove();
                }
            }
        } catch (Exception var20) {
            var20.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos1 = null;

        try {
            fos1 = new FileOutputStream(springConfigFile);
            IOUtils.writeLines(lines, IOUtils.LINE_SEPARATOR, fos1, conf.getEncoding());
        } catch (Exception var18) {
            var18.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos1);
        }

    }

    private void removeSpringConfig(File projectDir, String s, GeneratorConfiguration conf) {
        File springConfigFile = new File(projectDir, "jd-scaffold-rpc/src/main/resources/spring/spring-config-rpc.xml");
        if(springConfigFile.exists()) {
            FileInputStream fis = null;
            List lines = null;

            try {
                fis = new FileInputStream(springConfigFile);
                lines = IOUtils.readLines(fis, conf.getEncoding());
                Iterator fos = lines.iterator();

                while(fos.hasNext()) {
                    if(((String)fos.next()).contains(s)) {
                        fos.remove();
                    }
                }
            } catch (Exception var20) {
                var20.printStackTrace();
            } finally {
                IOUtils.closeQuietly(fis);
            }

            FileOutputStream fos1 = null;

            try {
                fos1 = new FileOutputStream(springConfigFile);
                IOUtils.writeLines(lines, IOUtils.LINE_SEPARATOR, fos1, conf.getEncoding());
            } catch (Exception var18) {
                var18.printStackTrace();
            } finally {
                IOUtils.closeQuietly(fos1);
            }

        }
    }

    private void removeWebSpringConfig(File projectDir, String s, GeneratorConfiguration conf) {
        File springConfigFile = new File(projectDir, "jd-scaffold-web/src/main/resources/spring/spring-config.xml");
        FileInputStream fis = null;
        List lines = null;

        try {
            fis = new FileInputStream(springConfigFile);
            lines = IOUtils.readLines(fis, conf.getEncoding());
            Iterator fos = lines.iterator();

            while(fos.hasNext()) {
                if(((String)fos.next()).contains(s)) {
                    fos.remove();
                }
            }
        } catch (Exception var20) {
            var20.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos1 = null;

        try {
            fos1 = new FileOutputStream(springConfigFile);
            IOUtils.writeLines(lines, IOUtils.LINE_SEPARATOR, fos1, conf.getEncoding());
        } catch (Exception var18) {
            var18.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos1);
        }

    }

    private void removeCommonProperties(File projectDir, String prefix, GeneratorConfiguration conf) {
        File commonPropertiesFile = new File(projectDir, "jd-scaffold-web/src/main/resources/properties/rpc.properties");
        FileInputStream fis = null;
        List lines = null;

        try {
            fis = new FileInputStream(commonPropertiesFile);
            lines = IOUtils.readLines(fis, conf.getEncoding());
            Iterator fos = lines.iterator();

            while(fos.hasNext()) {
                if(((String)fos.next()).startsWith(prefix)) {
                    fos.remove();
                }
            }
        } catch (Exception var20) {
            var20.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos1 = null;

        try {
            fos1 = new FileOutputStream(commonPropertiesFile);
            IOUtils.writeLines(lines, IOUtils.LINE_SEPARATOR, fos1, conf.getEncoding());
        } catch (Exception var18) {
            var18.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos1);
        }

    }

    private void generatePackageDirectory(File projectDir, GeneratorConfiguration conf) throws IOException {
        FileUtils.forceMkdir(new File(conf.getCommonPath()));
        FileUtils.forceMkdir(new File(conf.getDaoPath()));
        FileUtils.forceMkdir(new File(conf.getDomainPath()));
        if(conf.isUseIsRpcModule()) {
            FileUtils.forceMkdir(new File(conf.getIsRpcPath()));
            FileUtils.forceMkdir(new File(conf.getSafApiPath()));
        }

        FileUtils.forceMkdir(new File(conf.getManagerPath()));
        if(conf.isUseRpcModule()) {
            FileUtils.forceMkdir(new File(conf.getRpcPath()));
        }

        FileUtils.forceMkdir(new File(conf.getServicePath()));
        FileUtils.forceMkdir(new File(conf.getControllerPath()));
        if(conf.isUseWorkModule()) {
            FileUtils.forceMkdir(new File(conf.getWorkPath()));
        }

    }

    private void removeUnusedDependencies(File projectDir, GeneratorConfiguration conf) {
        this.removeUnusedDependenciesRpc(projectDir, conf);
        this.removeUnusedDependenciesDao(projectDir, conf);
    }

    private void removeUnusedDependenciesDao(File projectDir, GeneratorConfiguration conf) {
        File daoPomFile = new File(projectDir, "jd-scaffold-dao/pom.xml");
        if(daoPomFile.exists()) {
            FileInputStream daoFis = null;
            String daoContent = "";

            try {
                daoFis = new FileInputStream(daoPomFile);
                daoContent = IOUtils.toString(daoFis, conf.getEncoding());
                String daoFos;
                if(!conf.isUseMysql()) {
                    daoFos = "(([ ]*<mysql\\.version>.*</mysql\\.version>[ ]*))";
                    daoContent = this.replaceDependencies(daoFos, "${mysql.version", daoContent);
                }

                if(!conf.isUseOracle()) {
                    daoFos = "(([ ]*<ojdbc14\\.version>.*</ojdbc14\\.version>[ ]*))";
                    daoContent = this.replaceDependencies(daoFos, "${ojdbc14.version", daoContent);
                }

                if(!conf.isNeedSharding()) {
                    daoFos = "((\\s*<jd-db-sharding\\.version>.*</jd-db-sharding\\.version>\\s*))";
                    daoContent = this.replaceDependencies(daoFos, "${jd-db-sharding.version", daoContent);
                }
            } catch (Exception var19) {
                throw new RuntimeException("remove dependency error: " + var19.getMessage());
            } finally {
                IOUtils.closeQuietly(daoFis);
            }

            FileOutputStream daoFos1 = null;

            try {
                daoFos1 = new FileOutputStream(daoPomFile);
                IOUtils.write(daoContent, daoFos1, conf.getEncoding());
            } catch (Exception var17) {
                throw new RuntimeException("remove dependency error: " + var17.getMessage());
            } finally {
                IOUtils.closeQuietly(daoFos1);
            }

        }
    }

    private void removeUnusedDependenciesRpc(File projectDir, GeneratorConfiguration conf) {
        File parentPomFile = new File(projectDir, "jd-scaffold-rpc/pom.xml");
        if(parentPomFile.exists()) {
            FileInputStream fis = null;
            String content = "";

            try {
                fis = new FileInputStream(parentPomFile);
                content = IOUtils.toString(fis, conf.getEncoding());
                String fos;
                if(!conf.isUseMQ()) {
                    fos = "((\\s*<mq\\.version>.*</mq\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${mq.version", content);
                }

                if(!conf.isUseRedis()) {
                    fos = "((\\s*<redis-common-data\\.version>.*</redis-common-data\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${redis-common-data.version", content);
                }

                if(!conf.isUseSafServer() && conf.isUseSafClient() && !conf.isUseMQ()) {
                    fos = "((\\s*<saf\\.version>.*</saf\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${saf.version", content);
                }

                if(!conf.isUseMQ() && !conf.isUseSafServer() && !conf.isUseSafClient() && !conf.isUseZookeeper()) {
                    fos = "((\\s*<zookeeper\\.version>.*</zookeeper\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${zookeeper.version", content);
                }

                if(!conf.isUseZookeeper()) {
                    fos = "((\\s*<jd-configs\\.version>.*</jd-configs\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${jd-configs.version", content);
                }

                if(!conf.isNeedBaseUser()) {
                    fos = "((\\s*<dubbo\\.customer\\.version>.*</dubbo\\.customer\\.version>\\s*))";
                    content = this.replaceDependencies(fos, "${dubbo.customer.version", content);
                }
            } catch (Exception var19) {
                throw new RuntimeException("remove dependency error: " + var19.getMessage());
            } finally {
                IOUtils.closeQuietly(fis);
            }

            FileOutputStream fos1 = null;

            try {
                fos1 = new FileOutputStream(parentPomFile);
                IOUtils.write(content, fos1, conf.getEncoding());
            } catch (Exception var17) {
                throw new RuntimeException("remove dependency error: " + var17.getMessage());
            } finally {
                IOUtils.closeQuietly(fos1);
            }

        }
    }

    private String replaceDependencies(String regexp, String needMatcherStr, String content) {
        if(StringUtils.isNotBlank(regexp)) {
            content = content.replaceAll(regexp, IOUtils.LINE_SEPARATOR + "        ");
        }

        if(StringUtils.isNotBlank(needMatcherStr)) {
            String reg = "\\s*<dependency>([\\s\\S])*?</dependency>";
            Matcher matcher = Pattern.compile(reg, 8).matcher(content);

            while(matcher.find()) {
                String matchStr = matcher.group();
                if(matchStr.contains(needMatcherStr)) {
                    content = content.replace(matchStr, "");
                }
            }
        }

        return content;
    }

    private void filterFile(File file, GeneratorConfiguration conf) throws IOException {
        String oldGroupId = "com\\.jd\\.scaffold";
        String oldArtifactId = "jd-scaffold";
        String oldPackageName = "com\\.jd\\.scaffold";
        String oldfolderName = "com\\jd\\scaffold";
        String content;
        File fis;
        if(file.getName().contains("jd-scaffold")) {
            content = file.getName().replaceAll("jd-scaffold", conf.getProjectName());
            fis = new File(file.getParentFile(), content);
            file.renameTo(fis);
            file = fis;
        }

        if(file.getPath().contains("com\\jd\\scaffold")) {
            content = file.getPath().replace("com\\jd\\scaffold", FilenameUtils.concat(conf.getBasePackage().replace(".", File.separator), conf.getProjectName()));
            fis = new File(content);
            FileUtils.forceMkdir(fis);
            JarUtils.copyResourcesRecursivelyExcludeTop(file.toURL(), fis);
            FileUtils.deleteQuietly(file);
            file = fis;
        }

        if(!file.isDirectory()) {
            content = "";
            FileInputStream var27 = null;
            FileOutputStream var26 = null;

            try {
                var27 = new FileInputStream(file);
                content = IOUtils.toString(var27, conf.getEncoding());
            } catch (Exception var22) {
                throw new RuntimeException("replace file content error : " + file.getAbsolutePath());
            } finally {
                IOUtils.closeQuietly(var27);
            }

            try {
                var26 = new FileOutputStream(file);
                content = content.replaceAll("com\\.jd\\.scaffold", conf.getBasePackage() + "." + conf.getProjectName().replace(".", "\\."));
                content = content.replaceAll("jd-scaffold", conf.getProjectName());
                content = content.replaceAll("com\\.jd\\.scaffold", conf.getBasePackage() + "\\." + conf.getProjectName());
                IOUtils.write(content, var26, conf.getEncoding());
            } catch (Exception var20) {
                throw new RuntimeException("replace file content error : " + file.getAbsolutePath());
            } finally {
                IOUtils.closeQuietly(var26);
            }

        } else {
            File[] e;
            int fos = (e = file.listFiles()).length;

            for(int var25 = 0; var25 < fos; ++var25) {
                File var24 = e[var25];
                this.filterFile(var24, conf);
            }

        }
    }
}

